package org.example.java8time;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/***
 * @Author xiangjd
 * @Description //时间工具类
 * @Date 3:34 下午 2021/2/4
 * @return
 **/
public class DateUtils {


    /**
     *
     */
    private DateUtils() {
        super();
    }

    /**
     * 解析模板：yyyy-MM-dd HH-mm-ss
     */
    public static final int YMD_HMS = 0;

    /**
     * 解析模板：yyyy-MM-dd HH-mm
     */
    public static final int YMD_HM = 1;

    /**
     * 解析模板：yyyy-MM-dd
     */
    public static final int YMD = 2;

    /**
     * 解析模板：yyyy-MM
     */
    public static final int YM = 3;

    /**
     * 解析模板：yyyy
     */
    public static final int Y = 4;

    /**
     * 解析模板：HH-mm-ss
     */
    public static final int HMS = 5;

    /**
     * 解析模板：HH-mm
     */
    public static final int HM = 6;

    /**
     * 解析模板：yyyy年MM月dd日HH时mm分ss秒
     */
    public static final int CN_YMD_HMS = 7;

    /**
     * 解析模板：yyyy年MM月dd日HH时mm分
     */
    public static final int CN_YMD_HM = 8;

    /**
     * 解析模板：yyyy年MM月dd日
     */
    public static final int CN_YMD = 9;

    /**
     * 解析模板：yyyy年MM月
     */
    public static final int CN_YM = 10;

    /**
     * 解析模板：yyyy年
     */
    public static final int CN_Y = 11;

    /**
     * 解析模板：HH时mm分ss秒
     */
    public static final int CN_HMS = 12;

    /**
     * 解析模板：HH时mm分
     */
    public static final int CN_HM = 13;

    /**
     * subString ten
     */
    private static final int TEN = 10;

    /**
     * subString eleven
     */
    private static final int ELEVEN = 11;

    /**
     * formatter
     */
    private static final DateTimeFormatter[] FORMATTER = new DateTimeFormatter[]{
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy-MM").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy年MM月dd日").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy年MM月").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("yyyy年").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("HH时mm分ss秒").withZone(ZoneId.systemDefault()),
            DateTimeFormatter.ofPattern("HH时mm分").withZone(ZoneId.systemDefault()),};

    /**
     * date转LocalDateTime
     *
     * @param date Date
     * @return LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * date转LocalDate
     *
     * @param date Date
     * @return LocalDate
     */
    public static LocalDate date2LocalDate(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return localDateTime.toLocalDate();
    }

    /**
     * date转LocalTime
     *
     * @param date Date
     * @return LocalTime
     */
    public static LocalTime date2LocalTime(Date date) {
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return localDateTime.toLocalTime();
    }

    /**
     * localDateTime转Date
     *
     * @param localDateTime LocalDateTime
     * @return Date
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * 字符串解析为LocalDate
     *
     * @param cs          字符串
     * @param formatIndex 模板索引
     * @return LocalDate
     */
    public static LocalDate parseLocalDate(CharSequence cs, int formatIndex) {
        return LocalDate.parse(cs, FORMATTER[formatIndex]);
    }

    /**
     * 字符串解析为LocalTime
     *
     * @param cs          字符串
     * @param formatIndex 模板索引
     * @return LocalTime
     */
    public static LocalTime parseLocalTime(CharSequence cs, int formatIndex) {
        return LocalTime.parse(cs, FORMATTER[formatIndex]);
    }

    /**
     * 字符串解析为LocalDateTime
     *
     * @param cs          字符串
     * @param formatIndex 模板索引
     * @return LocalDateTime
     */
    public static LocalDateTime parseLocalDateTime(CharSequence cs, int formatIndex) {
        return LocalDateTime.parse(cs, FORMATTER[formatIndex]);
    }

    /**
     * 字符串解析为Instant
     *
     * @param cs          字符串
     * @param formatIndex 模板索引
     * @return Instant
     */
    public static Instant parseInstant(CharSequence cs, int formatIndex) {
        LocalDateTime localDateTime = parseLocalDateTime(cs, formatIndex);
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    /**
     * 字符串解析为Date
     *
     * @param cs          字符串
     * @param formatIndex 模板索引
     * @return Date
     */
    public static Date parseDate(CharSequence cs, int formatIndex) {
        Instant instant = parseInstant(cs, formatIndex);
        return Date.from(instant);
    }

    /**
     * TemporalAccessor格式化为字符串
     *
     * @param temporal    TemporalAccessor
     * @param formatIndex 模板索引
     * @return 字符串
     */
    public static String formatTemporal(TemporalAccessor temporal, int formatIndex) {
        return FORMATTER[formatIndex].format(temporal);
    }

    /**
     * Date格式化为字符串
     *
     * @param date        Date
     * @param formatIndex 模板索引
     * @return 字符串
     */
    public static String formatDate(Date date, int formatIndex) {
        return formatTemporal(date.toInstant(), formatIndex);
    }

    /**
     * yyyy-MM-dd HH-mm-ss 截取 yyyy-MM-dd
     *
     * @param cs 字符串
     * @return yyyy-MM-dd
     */
    public static String subYmd(CharSequence cs) {
        CharSequence subSequence = cs.subSequence(0, TEN);
        return subSequence.toString();
    }

    /**
     * yyyy-MM-dd HH-mm-ss 截取 HH-mm-ss
     *
     * @param cs 字符串
     * @return HH-mm-ss
     */
    public static String subHms(CharSequence cs) {
        CharSequence subSequence = cs.subSequence(ELEVEN, cs.length());
        return subSequence.toString();
    }

    /**
     * 获取最早时间
     *
     * @param date Date
     * @return 最早时间
     */
    public static Date getDayStart(Date date) {
        LocalDate localDate = date2LocalDate(date);
        LocalDateTime localDateTime = localDate.atStartOfDay();
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取最晚时间
     *
     * @param date Date
     * @return 最晚时间
     */
    public static Date getDayEnd(Date date) {
        LocalDate localDate = date2LocalDate(date);
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取当天开始时间
     *
     * @return 当天开始时间
     */
    public static Date getTodayStart() {
        LocalDateTime localDateTime = LocalDate.now().atStartOfDay();
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取当天结束时间
     *
     * @return 当天结束时间
     */
    public static Date getTodayEnd() {
        LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取昨日开始时间
     *
     * @return 昨日开始时间
     */
    public static Date getYesterdayStart() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.minusDays(1L);
        LocalDateTime localDateTime = localDate.atStartOfDay();
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取昨日结束时间
     *
     * @return 昨日结束时间
     */
    public static Date getYesterdayEnd() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.minusDays(1L);
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取本周开始时间
     *
     * @return 本周开始时间
     */
    public static Date getWeekStart() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDateTime localDateTime = localDate.atStartOfDay();
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取本周结束时间
     *
     * @return 本周结束时间
     */
    public static Date getWeekEnd() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取本月开始时间
     *
     * @return 本月开始时间
     */
    public static Date getMonthStart() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.with(TemporalAdjusters.firstDayOfMonth());
        LocalDateTime localDateTime = localDate.atStartOfDay();
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取本月结束时间
     *
     * @return 本月结束时间
     */
    public static Date getMonthEnd() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取本年开始时间
     *
     * @return 本年开始时间
     */
    public static Date getYearStart() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.with(TemporalAdjusters.firstDayOfYear());
        LocalDateTime localDateTime = localDate.atStartOfDay();
        return localDateTime2Date(localDateTime);
    }

    /**
     * 获取本年结束时间
     *
     * @return 本年结束时间
     */
    public static Date getYearEnd() {
        LocalDate localDate = LocalDate.now();
        localDate = localDate.with(TemporalAdjusters.lastDayOfYear());
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MAX);
        return localDateTime2Date(localDateTime);
    }


}